import { AppConsts } from '/@/abpPro/AppConsts';
import { defineComponent } from 'vue';
import {
  ISortCondition,
  SortType,
  ITableFilter,
  ITableSorter,
} from '/@/shared/component-base/interfaces';
import AppCompoentBase from '/@/shared/component-base/app-component-base';
import {
  ListViewsServiceProxy,
  IListViewDto,
  ButtonGroupsServiceProxy,
  IButtonGroupsDto,
  PageFiltersServiceProxy,
  IPageFilterDto,
  IPageFilterElementDto,
} from '/@/shared/service-proxies';
import mittEvent from '../utils/mitt';
import resizeMixin from './resize-mixin';
import GDynamicTableToolbar from '../components/toolbar/index.vue';
import GDynamicTableBody from '../components/table/index.vue';
import GDynamicTableSearch from '../components/search/index.vue';
import ColumnColorConfigModal from '../components/modal/column-color-config-modal.vue';
import ListConfigModal from '../components/modal/list-config-modal.vue';
import QueryConfigModal from '../components/modal/query-config-modal.vue';
import ExportDataMixin from './export-data-mixin';
export default defineComponent({
  components: {
    GDynamicTableToolbar,
    GDynamicTableBody,
    GDynamicTableSearch,
    ColumnColorConfigModal,
    QueryConfigModal,
    ListConfigModal,
  },
  mixins: [ExportDataMixin, resizeMixin, AppCompoentBase, ExportDataMixin],
  props: {
    type: {
      type: String,
      required: true,
      default: '',
    },
    fetch: {
      type: Function,
      required: true,
    },
    isPage: {
      type: Boolean,
      default: true,
    },
    extraHeight: {
      type: Number,
      default: 0,
    },
    rowKey: {
      type: String,
      required: true,
      default: 'id',
    },
    /** 分页情况下, 自定义接口返回data,total 的字段 */
    resultNames: {
      type: Object,
      default: {
        data: 'items',
        total: 'totalCount',
      },
    },
    /** 是否显示导出 */
    showExport: {
      type: Boolean,
      default: false,
    },
    showSelect: {
      type: Boolean,
      default: true,
      required: true,
    },
    /** 控制表格操作栏按钮隐藏 */
    showActionBtn: {
      type: Function,
    },
    exportConfig: {
      type: Object,
      default: {
        filename: 'Data',
        formartColumn: (field, value) => {
          return value;
        },
      },
    },
  },
  emits: ['fetch-success', 'fetch-error', 'action-click'],
  data() {
    return {
      /** api相关  */
      /** 列表配置JSON */
      listViewJson: {} as IListViewDto,
      listViewsServiceProxy: new ListViewsServiceProxy(this.$apiUrl, this.$api),
      /** 按钮组配置JSON */
      buttonGroupsJson: {} as IButtonGroupsDto,
      buttonGroupsServiceProxy: new ButtonGroupsServiceProxy(this.$apiUrl, this.$api),
      /** 表格搜索 */
      pageFiltersServiceProxy: new PageFiltersServiceProxy(this.$apiUrl, this.$api),
      /** 搜索表单配置JSON */
      pageFilterJson: {} as IPageFilterDto,
      /** 表格数据 */
      dataSources: [],
      /** 搜索数据 */
      searchForm: {},

      /** 配置项相关 */

      /** 表格加载状态 */
      loading: false,
      /** 是否显示顶部操作栏 */
      isToolbar: false,
      /** 选中行key */
      selectedRowKeys: [] as Array<string | number>,
      /** 选中行数据 */
      selectedRow: [],
      // 表格参数
      tableProps: {
        /** 是否展示外边框和列边框 */
        bordered: true,
        /** 是否显示表头 */
        showHeader: true,
        /**	表格大小 */
        size: 'default',
        /** 列表项是否可选择 */
        rowSelection: {
          /** checkable 状态下节点选择完全受控（父子数据选中状态不再关联） */
          checkStrictly: true,
          /** 多选/单选 */
          type: this.rowSelectionType,
          /** 去掉『全选』『反选』两个默认选项 */
          hideDefaultSelections: false,
          /** 指定选中项的 key 数组，需要和 onChange 进行配合 */
          selectedRowKeys: [],
          /** 选中项发生变化时的回调 */
          onChange: (selectedRowKeys: any) => {
            this.selectedRowKeys = selectedRowKeys;
          },
        },
        rowKey: (record) => record[this.rowKey],
        /** 分页器，参考配置项或 pagination文档，设为 false 时不展示和进行分页 */
        pagination: this.pagination,
        customRow: (record) => {
          return {
            onClick: (event) => {
              this.$emit('customRow', record);
              if (!this.getRowSelectionType()) return;
              if (this.getRowSelectionType() != 'radio' && this.getRowSelectionType() != 'checkbox')
                return;
              // 设置点击该行被禁用时不允许选中
              if (
                this.getRowSelection().hasOwnProperty('getCheckboxProps') &&
                this.getRowSelection().getCheckboxProps(record).disabled
              )
                return;
              this.selectRow(record);
            },
          };
        },
      } as any,
      pagination: {
        /** 分页大小 */
        pageSize: 20,
        /** 分页选项 */
        pageSizeOptions: ['20', '50', '100', '200'],
        /** 当前页 */
        current: 1,
        /** 总页数 */
        totalPages: 1,
        /** 总记录数 */
        total: 0,
        showQuickJumper: true,
        showSizeChanger: true,
        showTotal: this.showTotalFun,
        hideOnSinglePage: false,
      } as any,
      pageRange: [1, 1],
      /** 排序条件 - 表达式 */
      sortConditions: [] as ISortCondition[],
      /** 排序条件  */
      sorting: '',
      /** 筛选条件 */
      filterConditions: {},

      /**
       * ref
       * 按钮组
       * {
       *  refName
       *  event
       * }
       * 列表 */
      refList: [] as any,
    };
  },
  computed: {
    /** 表格选择功能(多选/单选) */
    rowSelectionType() {
      return this.listViewJson.rowSelection || 'checkbox';
    },
  },
  watch: {
    selectedRowKeys(val) {
      if (this.getRowSelectionType()) {
        this.setRowSelection('selectedRowKeys', val);
      }
    },
    listViewJson: {
      handler(val) {
        if (!val.rowSelection) {
          this.tableProps['rowSelection'] = null;
          return;
        } else {
          this.setRowSelection('type', val.rowSelection);
        }
      },
      deep: true,
    },
    pagination: {
      handler(val) {
        this.tableProps.pagination = val;
      },
      deep: true,
    },
  },
  mounted() {
    this.registerBottomShow();
    this.resize();
    if (this.getRowSelectionType()) {
      this.tableProps.rowSelection.selectedRowKeys = this.selectedRowKeys as any;
    }
  },
  created() {
    this.init(this.type);
  },
  beforeUnmount() {
    // 销毁前注销监听
    mittEvent.off('formDataChange');
  },
  methods: {
    /********************************************************** 组件外部实现使用方法 start ************************************************************************ */
    /** 获取Ref*/
    getRef(key) {
      const idx = this.refList.findIndex((item) => {
        return item.Name == key;
      });
      if (idx != -1) {
        //通过key获取的指定的Ref
        const isType = this.refList[idx].Instance;
        console.log(isType);
        /**判断类型如果是数组返回第0个，是对象直接返回 */
        if (Array.isArray(isType)) {
          return isType[0];
        } else {
          return isType;
        }
      } else {
        return undefined;
      }
    },
    /**填充Ref到refList数组 */
    setRef(item: any) {
      if (!!item) {
        this.refList.push(item);
      }
    },

    /** 设置表格参数 */
    setProps(key: string, val: any) {
      this.tableProps[key] = val;
    },
    /** 获取表格参数 */
    getProps() {
      return this.tableProps;
    },
    /**设置列表项配置 */
    setRowSelection(key: string, val: any) {
      this.tableProps.rowSelection[key] = val;
    },
    /**获取列表项配置 */
    getRowSelection() {
      return this.tableProps.rowSelection;
    },
    /** 获取表格 多选/单选 */
    getRowSelectionType() {
      return this.listViewJson.rowSelection || null;
    },
    /** 刷新数据 */
    reload() {
      this.fetchData();
    },
    /** 刷新数据，跳转第一页 */
    reloadGoFirstPage() {
      if (this.getShowPagination()) {
        this.pagination.current = 1;
      }
      this.fetchData();
    },
    /** 说明: 重新计算表格高度 */
    redoHeight() {},
    /** 设置表格 loading 状态 */
    setLoading(loading: boolean) {
      this.loading = loading;
    },
    /** 获取表格数据 */
    getDataSource() {
      return this.dataSources;
    },
    /** 获取后端接口原始数据 */
    getRawDataSource() {},
    /** 获取表头数据 */
    getColumns() {
      return this.listViewJson.listViewColumns || [];
    },
    /** 设置表格数据 */
    setTableData(data: never[]) {
      this.dataSources = data;
    },
    /** 设置分页信息 */
    setPagination(pagination) {
      if (this.getShowPagination()) {
        this.pagination = pagination;
      }
    },
    /** 根据 key 删除取消选中行 */
    deleteSelectRowByKey(key: string | number) {
      if (!!key) {
        const arr = this.selectedRowKeys.filter((item: string | number) => {
          return item != key;
        });
        this.setSelectedRowKeys(arr);
      }
    },
    /** 获取选中行的 keys */
    getSelectRowKeys() {
      return this.selectedRowKeys;
    },
    /** 获取选中行的 rows */
    getSelectRows() {},
    /** 清空选中行 */
    clearSelectedRowKeys() {
      this.selectedRowKeys = [];
    },
    /** 设置选中行 */
    setSelectedRowKey(rowKey: string | number) {
      this.selectedRowKeys.push(rowKey);
    },
    setSelectedRowKeys(rowKeys: Array<string | number>) {
      this.selectedRowKeys = rowKeys;
    },
    /** 获取当前分页信息 */
    getPaginationRef() {
      return this.pagination;
    },
    /** 获取当前是否显示分页 */
    getShowPagination() {
      return !!this.pagination && this.isPage;
    },
    /** 设置当前是否显示分页 */
    setShowPagination(show: boolean) {
      this.pagination = show;
    },
    /** 更新表格数据 */
    updateTableData() {},
    /** 根据唯一的 rowKey 更新指定行的数据.可用于不刷新整个表格而局部更新数据 */
    updateTableDataRecord() {},
    /** 根据唯一的rowKey 动态删除指定行的数据.可用于不刷新整个表格而局部更新数据 */
    deleteTableDataRecord() {},
    /** 可根据传入的 index 值决定插入数据行的位置，不传则是顺序插入，可用于不刷新整个表格而局部更新数据 */
    insertTableDataRecord() {},
    /**如果开启了搜索区域。可以通过该函数获取表单对象函数进行操作 */
    getForm() {
      return this.searchForm || {};
    },
    /**如果开启了搜索区域。可以通过该函数获取表单对象函数进行操作 */
    setForm(val: {}) {
      this.searchForm = val;
    },
    /** 设置搜索列的值 */
    setFormField(key: string, val: any) {
      this.searchForm[key] = val;
    },
    /** 获取搜索列的值 */
    getFormField(key: string) {
      return this.searchForm[key];
    },
    /** 展开树形表格 */
    expandAll() {},
    /** 折叠树形表格 */
    collapseAll() {},

    /** 获取请求参数 */
    getSearchProps() {
      let params = {};
      // 请求分页数据
      const req = {
        maxResultCount: 0,
        skipCount: 0,
        sorting: '',
      };
      if (this.getShowPagination()) {
        req.maxResultCount = this.pagination.pageSize;
        req.skipCount = (this.pagination.current - 1) * this.pagination.pageSize;
      }
      req.sorting = this.sorting;
      params = Object.assign(params, this.getForm());

      return { ...params, ...req };
    },
    /** 获取单个搜索数据 key-value */
    getPageFilter(fileName: string) {
      const filters = this.getSearchProps();
      if (filters.hasOwnProperty(fileName)) {
        return filters[fileName];
      }
      return null;
    },
    /** 获取所有搜索数据 key-value */
    getPageFilterAll() {
      return this.getForm();
    },
    /** 获取特殊处理所有搜索数据 array */
    getFormatPageFilterAll() {
      const basicData = this.getForm();
      const result: any = [];
      for (const key in basicData) {
        const queryType = !!this.pageFilterJson.pageFilterElements
          ? this.pageFilterJson.pageFilterElements.find((item: IPageFilterElementDto) => {
              return item.field == key;
            })?.queryType ?? null
          : null;
        result.push({
          key: key,
          value: basicData[key],
          queryType,
        });
      }
      return result;
    },

    /********************************************************** 组件外部实现使用方法 end ************************************************************************ */

    /********************************************************** 组件内部实现使用方法 start ************************************************************************ */

    /** 初始化 */
    init(type: string) {
      if (!this.isPage) {
        this.setShowPagination(false);
      }
      const column = this.getColumnsOfListView(type);
      const buttonGroups = this.getButtonGroups(type);
      const pageFilters = this.getPageFilters(type);
      this.setLoading(true);
      Promise.all([column, buttonGroups, pageFilters])
        .then((res) => {
          this.listViewJson = res[0] as IListViewDto;
          this.buttonGroupsJson = res[1] as IButtonGroupsDto;
          this.pageFilterJson = res[2] as IPageFilterDto;
          this.enableMonitor();
          this.initButtonConfig(this.buttonGroupsJson);
        })
        .finally(() => {
          this.setLoading(false);
          this.fetchData();
        });
    },

    /** 获取按钮组配置 */
    getButtonGroups(type: string): Promise<IButtonGroupsDto> {
      return new Promise((resolve, reject) => {
        if (!type) {
          reject('The type cannot be empty');
          return;
        }
        const userId = this.abpSession.userId;
        this.buttonGroupsServiceProxy
          .getButtonGroups(type, userId)
          .then((res: IButtonGroupsDto) => {
            resolve(res);
          })
          .catch((err) => {
            reject(err);
          });
      });
    },
    /** 获取列表配置 */
    getColumnsOfListView(type: string): Promise<IListViewDto> {
      return new Promise((resolve, reject) => {
        if (!type) {
          reject('The type cannot be empty');
          return;
        }
        const userId = this.abpSession.userId;
        this.listViewsServiceProxy
          .getColumnsOfListView(type, userId)
          .then((res: IListViewDto) => {
            resolve(res);
          })
          .catch((err) => {
            reject(err);
          });
      });
    },
    /** 获取表格搜索配置 */
    getPageFilters(type: string): Promise<IPageFilterDto> {
      return new Promise((resolve, reject) => {
        if (!type) {
          reject('The type cannot be empty');
          return;
        }
        const userId = this.abpSession.userId;
        this.pageFiltersServiceProxy
          .getPageFilter(type, userId)
          .then((res: IPageFilterDto) => {
            resolve(res);
          })
          .catch((err) => {
            reject(err);
          });
      });
    },
    /** 获取表格数据 */
    fetchData() {
      if (!!fetch) {
        this.setLoading(true);
        this.fetch()
          .then((res: any) => {
            if (this.getShowPagination()) {
              console.log(this.resultNames);

              this.pagination.total = res[this.resultNames.total];
              this.pagination.totalPages = Math.ceil(
                this.pagination.total / this.pagination.pageSize,
              );
              this.pageRange = [
                (this.pagination.current - 1) * this.pagination.pageSize + 1,
                this.pagination.current * this.pagination.pageSize,
              ];
              this.setTableData(res[this.resultNames.data]);
            } else {
              this.setTableData(res);
            }
            this.setSelectedRowKeys([]);
            this.$emit('fetch-success', res);
          })
          .catch((error: any) => {
            this.$emit('fetch-error', error);
          })
          .finally(() => {
            this.setLoading(false);
            // 重新计算
            this.resize();
          });
      } else {
        console.log(`请重写 fetch 函数`);
      }
    },
    /** 获取导出数据 */
    getExportExcelData() {
      return new Promise((resolve, reject) => {
        if (!!fetch) {
          this.setLoading(true);
          this.fetch()
            .then((res: any) => {
              if (this.getShowPagination()) {
                resolve(res[this.resultNames.data]);
              } else {
                resolve(res);
              }
            })
            .catch((error: any) => {
              reject(error);
            })
            .finally(() => {
              this.setLoading(false);
            });
        } else {
          resolve([]);
        }
      });
    },
    /** 获取导出全部数据 */
    getExportExcelAllData() {
      return new Promise((resolve, reject) => {
        if (!!fetch) {
          this.setLoading(true);
          this.fetch({
            maxResultCount: AppConsts.export.maxResultCount,
            skipCount: AppConsts.export.skipCount,
          })
            .then((res: any) => {
              if (this.getShowPagination()) {
                resolve(res[this.resultNames.data]);
              } else {
                resolve(res);
              }
            })
            .catch((error: any) => {
              reject(error);
            })
            .finally(() => {
              this.setLoading(false);
            });
        } else {
          resolve([]);
        }
      });
    },
    /** 初始化按钮组 */
    initButtonConfig(config: IButtonGroupsDto) {
      this.isToolbar = !!config.buttonConfigs && config.buttonConfigs.length > 0 ? true : false;
    },

    handleSearchClick(val) {
      this.setForm(val);
      this.reloadGoFirstPage();
    },
    handleTableChange({ pagination, filters, sorter, currentDataSource }) {
      if (this.getShowPagination()) {
        this.pagination.current = pagination.current;
        this.pagination.pageSize = pagination.pageSize;
      }
      const sortMap = this.toSortMap(sorter);
      this.sortConditions = this.toSortConditions(sortMap);
      this.sorting = this.toSortingString(sortMap);
      // 更新筛选条件
      // const filterMap = this.toFilterValues(filters);
      // const filterHasChange = this.updateFilterValues(filterMap);
      // console.log(filterMap);

      // 筛选条件发生改变，需要跳转到第一页
      // if (filterHasChange) {
      //   this.pagination.current = 1;
      // }

      this.reload();
    },
    handleActionClick(type: string, recode: any) {
      // 表格相关
      const tableConfig = ['ListConfig', 'PersonalizedConfig', 'QueryConfig', 'ColumnColorConfig'];
      // 导出相关
      const exportDataConfig = ['Export', 'BulkExport'];

      if (tableConfig.includes(type)) {
        switch (type) {
          case 'ListConfig':
            this.handleOpenColumnConfig();
            break;
          case 'ColumnColorConfig':
            this.handleOpenColumnColorConfig();
            break;
          case 'QueryConfig':
            this.handleOpenQueryrConfig();
            break;
          default:
            break;
        }
      } else if (exportDataConfig.includes(type)) {
        // 表头
        const exportHeader = this.formatExcelHeader(this.getColumns());
        // 数据
        let exportData: Array<any> = [];
        // 获取数据
        if (type == 'Export') {
          // 格式化数据
          this.getExportExcelData().then((res) => {
            exportData = this.formatExcelData(type, this.getColumns(), res);
            this.export(exportHeader, exportData);
          });
        } else if (type == 'BulkExport') {
          this.getExportExcelAllData().then((res) => {
            exportData = this.formatExcelData(type, this.getColumns(), res);
            this.export(exportHeader, exportData);
          });
        }
        // 执行导出操作
      } else {
        this.$emit('action-click', type, recode);
      }
    },
    showTotalFun() {
      return this.l('TotalRecordsCount', this.pagination.total);
    },

    /**
     * 开启子组件监听
     * todo
     */
    enableMonitor() {
      mittEvent.off('formDataChange');
      mittEvent.on('formDataChange', (info: any) => {
        // 等待联动的属性(组件)列表
        const todolist = info.el.valueChange;
        // todo
        // 死数据
        todolist.forEach((item: string) => {
          this.setFormField(item, info.value == 1 ? '男' : '女');
        });
      });
    },
    /** 注册底部bottom打开事件 */
    registerBottomShow() {
      abp.event.on('bottomFixedChange', () => {
        this.resize();
      });
    },
    selectRow(record) {
      const idx = this.selectedRowKeys.findIndex((item) => {
        return item == record[this.rowKey];
      });
      if (idx != -1) {
        this.selectedRowKeys.splice(idx, 1);
      } else {
        this.selectedRowKeys.push(record[this.rowKey]);
      }
    },

    /** sorter转映射 */
    toSortMap(input: ITableSorter | ITableSorter[]): { [name: string]: SortType } {
      if (!input) {
        return {};
      }
      const sorters: ITableSorter[] = [];
      if (!Array.isArray(input)) {
        sorters.push(input);
      } else {
        sorters.push(...input);
      }
      const sortMap: { [name: string]: SortType } = {};
      for (const item of sorters) {
        if (!item.field) {
          continue;
        }
        if (!sortMap[item.field]) {
          if (!item.order) {
            continue;
          }
          sortMap[item.field] = item.order === 'ascend' ? SortType.Asc : SortType.Desc;
        }
      }

      return sortMap;
    },
    /** 排序转排序规则表达式 */
    toSortConditions(sortMap: { [name: string]: SortType }): ISortCondition[] {
      if (!sortMap) {
        return [];
      }

      let index = 0;
      const sortConditions: ISortCondition[] = [];
      // tslint:disable-next-line:forin
      for (const key in sortMap) {
        sortConditions.push({
          field: key,
          order: index++,
          type: sortMap[key],
        });
      }
      return sortConditions;
    },
    /** 排序转排序规则表达式字符串 */
    toSortingString(sortMap: { [name: string]: SortType }): string {
      if (!sortMap) {
        return '';
      }
      // 处理数据
      let sorting = '';
      // tslint:disable-next-line:forin
      for (const key in sortMap) {
        sorting += `${key} ${sortMap[key]},`;
      }

      // 截取最后的字符串
      if (sorting.endsWith(',')) {
        sorting = sorting.substr(0, sorting.length - 1);
      }

      return sorting;
    },
    /**
     * 映射筛选条件
     * @param filter 筛选条件信息
     */
    toFilterValues(filter: ITableFilter): { [name: string]: any } {
      const res = {};
      for (const key in filter) {
        const filterFieldIsArray = Array.isArray(this[key]);
        let val = filter[key];

        // 如果筛选条件字段不是数组
        // 并且当前筛选值是数组
        // 并且值长度为1，那么取第一条数据作为val
        if (!filterFieldIsArray && Array.isArray(val)) {
          val = val[0];
        }
        res[key] = val;
      }
      return res;
    },
    /** 更新filter */
    updateFilterValues(filterMap: { [name: string]: any }) {
      let existChange = false;
      for (const key in filterMap) {
        const currentVal = this[key];
        const newVal = filterMap[key];
        // 做比较
        if (currentVal !== newVal) {
          existChange = true;
        }
        // 更新值
        this[key] = newVal;
      }
      return existChange;
    },

    handleOpenColumnColorConfig() {
      this.modalHelper
        .create(ColumnColorConfigModal, { json: this.listViewJson })
        .subscribe((res) => {
          if (res) {
            this.init(this.type);
          }
        });
    },
    handleOpenColumnConfig() {
      this.modalHelper.create(ListConfigModal, { json: this.listViewJson }).subscribe((res) => {
        if (res) {
          this.init(this.type);
        }
      });
    },
    handleOpenQueryrConfig() {
      this.modalHelper.create(QueryConfigModal, { json: this.pageFilterJson }).subscribe((res) => {
        if (res) {
          this.init(this.type);
        }
      });
    },

    /********************************************************** 组件内部实现使用方法 start ************************************************************************ */
  },
});
